#pragma once

#if defined(WIN32) || defined(_WIN32)

#include "IOMultiplexer.h"

#include <winsock2.h>

namespace network {

    class Select : public IOMultiplexer {

    public:

        /**
          * @brief  创建一个select模型
          */
        Select();

        /**
          * @brief  设置select关注指定文件描述符的指定IO事件
          * @param  fd 要加入检测的文件描述符
          * @param  event_type 关注的IO事件
          * @retval 是否成功将事件添加到select模型上
          */
        bool add(int fd, EventType event) override;

        /**
          * @brief  修改select关注的事件类型
          * @param  fd    要修改的文件描述符
          * @param  event 要关注的类型
          * @retval 是否修改成功
          */
        bool mod(int fd, EventType event) override;

        /**
          * @brief  将select对象上指定的fd对应的master_read_set删除
          * @note   该函数在删除指定的fd后不会自动关闭该fd，请手动关闭
          * @param  要删除的fd
          * @retval 是否成功删除
          */
        bool del(int fd) override;

        /**
          * @brief  等待select文件描述符上的I/O事件
          * @note   select返回小于0时会抛出runtime_error异常
          * @param  reactor 反应堆指针
          * @retval 就绪事件个数
          */
        int dispatch(Reactor *reactor) override;

        ~Select() override = default;

    private:

        // 读描述符集合
        fd_set master_read_set_, read_set_;

        // 写描述符集合
        fd_set master_write_set_, write_set_;

        // 最大文件描述符
        int max_fd_;

        // 超时时长
        struct timeval timeout_;

    };

}

#endif
